// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
//
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.query.sections;

import org.dengues.designer.ui.database.editors.DBFileEditorInput;
import org.dengues.designer.ui.query.AbstractFormPage;
import org.dengues.model.database.DatabaseDiagram;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 2007-12-8 qiang.zhang $
 * 
 */
public abstract class AbstractSectionPart extends SectionPart {

    public static final int BUTTON_ADD = 0;

    public static final int BUTTON_EDIT = 1;

    public static final int BUTTON_REMOVE = 2;

    public static final int BUTTON_UP = 3;

    public static final int BUTTON_DOWN = 4;

    // SECTION CLIENT
    public static final int SECTION_CLIENT_MARGIN_TOP = 5;

    public static final int SECTION_CLIENT_MARGIN_BOTTOM = 5;

    // Should be 6; but, we minus 4 because the section automatically pads the
    // left margin by that amount
    public static final int SECTION_CLIENT_MARGIN_LEFT = 2;

    // Should be 6; but, we minus 4 because the section automatically pads the
    // right margin by that amount
    public static final int SECTION_CLIENT_MARGIN_RIGHT = 2;

    public static final int SECTION_CLIENT_HORIZONTAL_SPACING = 5;

    public static final int SECTION_CLIENT_VERTICAL_SPACING = 5;

    public static final int SECTION_CLIENT_MARGIN_HEIGHT = 0;

    public static final int SECTION_CLIENT_MARGIN_WIDTH = 0;

    public static final int DEFAULT_CLEAR_MARGIN = 2;

    // CLEAR
    public static final int CLEAR_MARGIN_TOP = DEFAULT_CLEAR_MARGIN;

    public static final int CLEAR_MARGIN_BOTTOM = DEFAULT_CLEAR_MARGIN;

    public static final int CLEAR_MARGIN_LEFT = DEFAULT_CLEAR_MARGIN;

    public static final int CLEAR_MARGIN_RIGHT = DEFAULT_CLEAR_MARGIN;

    public static final int CLEAR_HORIZONTAL_SPACING = 0;

    public static final int CLEAR_VERTICAL_SPACING = 0;

    public static final int CLEAR_MARGIN_HEIGHT = 0;

    public static final int CLEAR_MARGIN_WIDTH = 0;

    protected StructuredViewer viewerPart;

    /**
     * Qiang.Zhang.Adolf@gmail.com AbstractSectionPart class global comment. Detailled comment <br/>
     * 
     * $Id: Dengues.epf 2007-12-11 qiang.zhang $
     * 
     */
    private class SelectionHandler implements SelectionListener {

        public void widgetSelected(SelectionEvent e) {
            buttonSelected(e);
        }

        public void widgetDefaultSelected(SelectionEvent e) {
            buttonSelected(e);
        }

        private void buttonSelected(SelectionEvent e) {
            Integer index = (Integer) e.widget.getData();
            AbstractSectionPart.this.buttonSelected((Button) e.widget, index.intValue());
        }
    }

    protected AbstractFormPage dPage;

    private Composite fButtonContainer;

    private Button[] fButtons;

    private String[] fButtonLabels;

    protected DatabaseDiagram dbDiagram;

    public static final int SECTION_HEADER_VERTICAL_SPACING = 6;

    /**
     * Qiang.Zhang.Adolf@gmail.com AbstractSectionPart constructor comment.
     * 
     * @param formPage
     * @param parent
     * @param style
     * @param buttonLabels
     */
    public AbstractSectionPart(AbstractFormPage formPage, Composite parent, int style, String[] buttonLabels) {
        this(formPage, parent, style, true, buttonLabels);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com AbstractSectionPart constructor comment.
     * 
     * @param formPage
     * @param parent
     * @param style
     * @param titleBar
     * @param buttonLabels
     */
    public AbstractSectionPart(AbstractFormPage formPage, Composite parent, int style, boolean titleBar, String[] buttonLabels) {
        this(formPage, parent, style, titleBar);
        fButtonLabels = buttonLabels;
        createClient(getSection(), formPage.getManagedForm().getToolkit(), style);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com AbstractSectionPart constructor comment.
     * 
     * @param page
     * @param parent
     * @param style
     * @param titleBar
     */
    private AbstractSectionPart(AbstractFormPage page, Composite parent, int style, boolean titleBar) {
        super(parent, page.getManagedForm().getToolkit(), titleBar ? (ExpandableComposite.TITLE_BAR | style) : style);
        dPage = page;
        DBFileEditorInput input = (DBFileEditorInput) dPage.getEditor().getEditorInput();
        dbDiagram = input.getDbDiagram();
        initialize(page.getManagedForm());
        getSection().clientVerticalSpacing = SECTION_HEADER_VERTICAL_SPACING;
        getSection().setData("part", this); //$NON-NLS-1$
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createComposite".
     * 
     * @param parent
     * @param toolkit
     * @return
     */
    protected Composite createComposite(Composite parent, FormToolkit toolkit) {
        if (toolkit == null)
            return new Composite(parent, SWT.NULL);
        return toolkit.createComposite(parent);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createClient".
     * 
     * @param section
     * @param toolkit
     * @param style
     */
    protected void createClient(Section section, FormToolkit toolkit, int style) {
        Composite container = createClientContainer(section, 2, toolkit);
        container.setLayoutData(new GridData(GridData.FILL_BOTH));
        createControl(container, SWT.MULTI | style, 2, toolkit);
        MenuManager popupMenuManager = new MenuManager();
        IMenuListener listener = new IMenuListener() {

            public void menuAboutToShow(IMenuManager mng) {
                fillContextMenu(mng);
            }
        };
        popupMenuManager.addMenuListener(listener);
        popupMenuManager.setRemoveAllWhenShown(true);
        Control control = viewerPart.getControl();
        Menu menu = popupMenuManager.createContextMenu(control);
        control.setMenu(menu);
        toolkit.paintBordersFor(container);
        section.setClient(container);
        GridData gd = new GridData(GridData.FILL_BOTH);
        gd.minimumWidth = 250;
        gd.grabExcessVerticalSpace = true;
        section.setLayout(createClearGridLayout(false, 1));
        section.setLayoutData(gd);
    }

    protected final Composite createClientContainer(Composite parent, int span, FormToolkit toolkit) {
        Composite container = toolkit.createComposite(parent);
        container.setLayout(createSectionClientGridLayout(false, span));
        return container;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "fillContextMenu".
     * 
     * @param manager
     */
    protected void fillContextMenu(IMenuManager manager) {
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createControl".
     * 
     * @param parent
     * @param style
     * @param span
     * @param toolkit
     */
    protected void createControl(Composite parent, int style, int span, FormToolkit toolkit) {
        createMainTitle(parent, span, toolkit);
        createMainControl(parent, style, span - 1, toolkit);
        createButtons(parent, toolkit);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createButtons".
     * 
     * @param parent
     * @param toolkit
     */
    protected void createButtons(Composite parent, FormToolkit toolkit) {
        if (fButtonLabels != null && fButtonLabels.length > 0) {
            fButtonContainer = createComposite(parent, toolkit);
            GridData gd = new GridData(GridData.FILL_VERTICAL);
            fButtonContainer.setLayoutData(gd);
            fButtonContainer.setLayout(createButtonsLayout());
            fButtons = new Button[fButtonLabels.length];
            SelectionHandler listener = new SelectionHandler();
            for (int i = 0; i < fButtonLabels.length; i++) {
                String label = fButtonLabels[i];
                if (label != null) {
                    Button button = createButton(fButtonContainer, label, i, toolkit);
                    button.addSelectionListener(listener);
                    fButtons[i] = button;
                } else {
                    createEmptySpace(fButtonContainer, 1, toolkit);
                }
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createMainLabel".
     * 
     * @param parent
     * @param span
     * @param toolkit
     */
    protected void createMainTitle(Composite parent, int span, FormToolkit toolkit) {
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createMainControl".
     * 
     * @param parent
     * @param style
     * @param span
     * @param toolkit
     */
    protected abstract void createMainControl(Composite parent, int style, int span, FormToolkit toolkit);

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createButtonsLayout".
     * 
     * @return
     */
    protected GridLayout createButtonsLayout() {
        GridLayout layout = new GridLayout();
        layout.marginWidth = layout.marginHeight = 0;
        return layout;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "buttonSelected".
     * 
     * @param button
     * @param index
     */
    protected abstract void buttonSelected(Button button, int index);

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createButton".
     * 
     * @param parent
     * @param label
     * @param index
     * @param toolkit
     * @return
     */
    protected Button createButton(Composite parent, String label, int index, FormToolkit toolkit) {
        Button button;
        if (toolkit != null)
            button = toolkit.createButton(parent, label, SWT.PUSH);
        else {
            button = new Button(parent, SWT.PUSH);
            button.setText(label);
        }
        GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
        button.setLayoutData(gd);
        button.setData(new Integer(index));
        return button;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createEmptySpace".
     * 
     * @param parent
     * @param span
     * @param toolkit
     * @return
     */
    protected Label createEmptySpace(Composite parent, int span, FormToolkit toolkit) {
        Label label;
        if (toolkit != null) {
            label = toolkit.createLabel(parent, null);
        } else {
            label = new Label(parent, SWT.NULL);
        }
        GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
        gd.horizontalSpan = span;
        gd.widthHint = 0;
        gd.heightHint = 0;
        label.setLayoutData(gd);
        return label;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getButton".
     * 
     * @param index
     * @return
     */
    public final Button getButton(int index) {
        //
        if ((fButtons == null) || (index < 0) || (index >= fButtons.length)) {
            return null;
        }
        //
        return fButtons[index];
    }

    /**
     * For composites set as section clients. For composites containg form text.
     * 
     * @param makeColumnsEqualWidth
     * @param numColumns
     * @return
     */
    public final GridLayout createSectionClientGridLayout(boolean makeColumnsEqualWidth, int numColumns) {
        GridLayout layout = new GridLayout();

        layout.marginHeight = SECTION_CLIENT_MARGIN_HEIGHT;
        layout.marginWidth = SECTION_CLIENT_MARGIN_WIDTH;

        layout.marginTop = SECTION_CLIENT_MARGIN_TOP;
        layout.marginBottom = SECTION_CLIENT_MARGIN_BOTTOM;
        layout.marginLeft = SECTION_CLIENT_MARGIN_LEFT;
        layout.marginRight = SECTION_CLIENT_MARGIN_RIGHT;

        layout.horizontalSpacing = SECTION_CLIENT_HORIZONTAL_SPACING;
        layout.verticalSpacing = SECTION_CLIENT_VERTICAL_SPACING;

        layout.makeColumnsEqualWidth = makeColumnsEqualWidth;
        layout.numColumns = numColumns;

        return layout;
    }

    /**
     * For miscellaneous grouping composites. For sections (as a whole - header plus client).
     * 
     * @param makeColumnsEqualWidth
     * @param numColumns
     * @return
     */
    public final GridLayout createClearGridLayout(boolean makeColumnsEqualWidth, int numColumns) {
        GridLayout layout = new GridLayout();

        layout.marginHeight = CLEAR_MARGIN_HEIGHT;
        layout.marginWidth = CLEAR_MARGIN_WIDTH;

        layout.marginTop = CLEAR_MARGIN_TOP;
        layout.marginBottom = CLEAR_MARGIN_BOTTOM;
        layout.marginLeft = CLEAR_MARGIN_LEFT;
        layout.marginRight = CLEAR_MARGIN_RIGHT;

        layout.horizontalSpacing = CLEAR_HORIZONTAL_SPACING;
        layout.verticalSpacing = CLEAR_VERTICAL_SPACING;

        layout.makeColumnsEqualWidth = makeColumnsEqualWidth;
        layout.numColumns = numColumns;

        return layout;
    }
}
